package com.xyz.task;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.xyz.entity.mapper.*;
import com.xyz.entity.pojo.*;
import com.xyz.mqtt.MqttSendClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

// 定时任务
@EnableScheduling
@Component
@Transactional(rollbackFor = Exception.class)
public class MqttTask {

    private static final Logger logger = LoggerFactory.getLogger(MqttTask.class);

    @Autowired
    private MqttSendClient mqttSendClient;

    @Autowired
    private EquipmentInfoMapper equipmentInfoMapper;

    @Autowired
    private PartInfoMapper partInfoMapper;

    @Autowired
    private PartStockMapper partStockMapper;

    @Autowired
    private PartApplyMapper partApplyMapper;

    @Autowired
    private PartApplyDetailMapper partApplyDetailMapper;

    @Autowired
    private RepairWorkOrderMapper repairWorkOrderMapper;

    @Autowired
    private UpkeepWorkOrderMapper upkeepWorkOrderMapper;

    @Autowired
    private PatrolWorkOrderMapper patrolWorkOrderMapper;

    @Scheduled(fixedDelay = 30000)
    public void mqttReconnectionTask() {
        if (MqttSendClient.client == null || !MqttSendClient.client.isConnected()) {
            logger.warn("【MQTT定时重新连接】....................................................");
            mqttSendClient.reconnection();
        }
    }

    private static final String APP_ID = "1778312753395994688";
    private static final String DEFAULT_DEVICE_ID = "deviceManagerSys";
    private static final String DATA_TYPE = "runtime";
    private static final String VERSION = "1.0";

    private void sendMqtt(String deviceId, String dataName, String dataKey, Object dataValue, String dataUnit) {
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("dataTs", DateUtil.current());
        dataMap.put("dataUnit", dataUnit);
        dataMap.put("dataName", dataName);
        dataMap.put("dataKey", dataKey);
        dataMap.put("dataValue", dataValue);
        dataList.add(dataMap);

        Map<String, Object> map = new HashMap<>();
        map.put("appId", APP_ID);
        map.put("deviceId", deviceId);
        map.put("dataType", DATA_TYPE);
        map.put("version", VERSION);
        map.put("data", dataList);

        String jsonStr = JSONUtil.toJsonStr(map);
        mqttSendClient.publish(false, APP_ID + "/" + deviceId + "/" + DATA_TYPE + "/" + dataKey, jsonStr);
    }

    @Scheduled(cron = "0 * * * * ?")
    public void mqttMin() {
        sendMqtt(DEFAULT_DEVICE_ID, "系统在线状态", "Online", 1, "");
    }


    @Scheduled(cron = "0 0,10,20,30,40,50 * * * ?")
    public void mqttHour() {
        EquipmentInfoExample etExample = new EquipmentInfoExample();
        EquipmentInfoExample.Criteria etCriteria1 = etExample.createCriteria();
        etCriteria1.andIsDeleteEqualTo(0);
        int count1 = (int) equipmentInfoMapper.countByExample(etExample);
        sendMqtt(DEFAULT_DEVICE_ID, "设备总数", "DeviceCount", count1, "");

        etExample.clear();
        EquipmentInfoExample.Criteria etCriteria2 = etExample.createCriteria();
        etCriteria2.andIsScrapEqualTo(1);
        etCriteria2.andIsDeleteEqualTo(0);
        int count2 = (int) equipmentInfoMapper.countByExample(etExample);
        sendMqtt(DEFAULT_DEVICE_ID, "特种设备数", "SEDeviceCount", count2, "");

        etExample.clear();
        EquipmentInfoExample.Criteria etCriteria3 = etExample.createCriteria();
        etCriteria3.andEmStateEqualTo(3);
        etCriteria3.andIsDeleteEqualTo(0);
        int count3 = (int) equipmentInfoMapper.countByExample(etExample);
        sendMqtt(DEFAULT_DEVICE_ID, "故障设备数", "FaultDeviceCount", count3, "");

        etExample.clear();
        EquipmentInfoExample.Criteria etCriteria4 = etExample.createCriteria();
        etCriteria4.andEmStateEqualTo(1);
        etCriteria4.andIsDeleteEqualTo(0);
        int count4 = (int) equipmentInfoMapper.countByExample(etExample);
        sendMqtt(DEFAULT_DEVICE_ID, "正常运行设备数", "DeviceCountNormal", count4, "");

        int round = NumberUtil.round(NumberUtil.mul(NumberUtil.div(count4, count1), 100), 0).intValue();
        sendMqtt(DEFAULT_DEVICE_ID, "设备开动率", "DeviceStartUp Rate", round, "%");


        int count5 = 0;
        PartStockExample psExample = new PartStockExample();
        PartStockExample.Criteria psCriteria = psExample.createCriteria();
        psCriteria.andIsDeleteEqualTo(0);
        List<PartStock> psList = partStockMapper.selectByExample(psExample);
        for (PartStock ps : psList) {
            count5 += ps.getStock();
        }
        sendMqtt(DEFAULT_DEVICE_ID, "备件库存总数", "TotalSparePartsInventory", count5, "");


        Date date = new Date();

        int count6 = 0;
        PartApplyExample paExample = new PartApplyExample();
        PartApplyExample.Criteria paCriteria = paExample.createCriteria();
        paCriteria.andIsDeleteEqualTo(0);
        paCriteria.andApplyTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        List<PartApply> paList = partApplyMapper.selectByExample(paExample);
        List<Long> paIdList = CollStreamUtil.toList(paList, PartApply::getId);
        if (paIdList.size() > 0) {
            PartApplyDetailExample padExample = new PartApplyDetailExample();
            PartApplyDetailExample.Criteria padCriteria = padExample.createCriteria();
            padCriteria.andApplyIdIn(paIdList);
            List<PartApplyDetail> padList = partApplyDetailMapper.selectByExample(padExample);
            for (PartApplyDetail pad : padList) {
                count6 = pad.getNum();
            }
        }
        sendMqtt(DEFAULT_DEVICE_ID, "备件今日申请数", "SparePartsRequestCountToDay", count6, "");

        int count7 = 0;
        PartInfoExample piExample = new PartInfoExample();
        PartInfoExample.Criteria piCriteria = piExample.createCriteria();
        piCriteria.andIsDeleteEqualTo(0);
        List<PartInfo> piList = partInfoMapper.selectByExample(piExample);
        for (PartInfo pi : piList) {
            if (pi.getWarnStock() > pi.getStock()) {
                count7++;
            }
        }
        sendMqtt(DEFAULT_DEVICE_ID, "备件-库存不足种类数", "SparePartsInsufficientClassification", count7, "");

        RepairWorkOrderExample rwoExample = new RepairWorkOrderExample();
        int count8 = (int) repairWorkOrderMapper.countByExample(rwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维修-工单数", "RepairOrderCount", count8, "");

        RepairWorkOrderExample.Criteria rwoCriteria1 = rwoExample.createCriteria();
        rwoCriteria1.andCreateTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        int count9 = (int) repairWorkOrderMapper.countByExample(rwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维修-今日新增工单数", "RepairOrderCountToDayNew", count9, "");

        rwoExample.clear();
        RepairWorkOrderExample.Criteria rwoCriteria2 = rwoExample.createCriteria();
        rwoCriteria2.andRepStateBetween(2, 10);
        int count10 = (int) repairWorkOrderMapper.countByExample(rwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维修-处理中工单数", "RepairOrderCountProcessing", count10, "");

        rwoExample.clear();
        RepairWorkOrderExample.Criteria rwoCriteria3 = rwoExample.createCriteria();
        rwoCriteria3.andRepStateEqualTo(11);
        int count11 = (int) repairWorkOrderMapper.countByExample(rwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维修-已完成工单数", "RepairOrderCountFinish", count11, "");


        UpkeepWorkOrderExample uwoExample = new UpkeepWorkOrderExample();
        int count12 = (int) upkeepWorkOrderMapper.countByExample(uwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维保-工单总数", "MaintenanceOrderCount", count12, "");

        UpkeepWorkOrderExample.Criteria uwoCriteria1 = uwoExample.createCriteria();
        uwoCriteria1.andCreateTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        int count13 = (int) upkeepWorkOrderMapper.countByExample(uwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维保-今日新增数", "MaintenanceOrderCountToDayNew", count13, "");

        uwoExample.clear();
        UpkeepWorkOrderExample.Criteria uwoCriteria2 = uwoExample.createCriteria();
        uwoCriteria2.andUpkeepStateBetween(2, 10);
        int count14 = (int) upkeepWorkOrderMapper.countByExample(uwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维保-处理中数", "MaintenanceOrderCountProcessing", count14, "");

        uwoExample.clear();
        UpkeepWorkOrderExample.Criteria uwoCriteria3 = uwoExample.createCriteria();
        uwoCriteria3.andUpkeepStateEqualTo(11);
        int count15 = (int) upkeepWorkOrderMapper.countByExample(uwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "维保-已完成数", "MaintenanceOrderCountFinished", count15, "");


        PatrolWorkOrderExample pwoExample = new PatrolWorkOrderExample();
        int count16 = (int) patrolWorkOrderMapper.countByExample(pwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "巡检-工单总数", "PatrolInspectionOrderCount", count16, "");

        PatrolWorkOrderExample.Criteria pwoCriteria1 = pwoExample.createCriteria();
        pwoCriteria1.andCreateTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        int count17 = (int) patrolWorkOrderMapper.countByExample(pwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "巡检-今日新增数", "PatrolInspectionOrderCountToDayNew", count17, "");

        pwoExample.clear();
        PatrolWorkOrderExample.Criteria pwoCriteria2 = pwoExample.createCriteria();
        pwoCriteria2.andStateNotEqualTo(5);
        int count18 = (int) patrolWorkOrderMapper.countByExample(pwoExample);
        sendMqtt(DEFAULT_DEVICE_ID, "巡检-处理中数", "PatrolInspectionOrderCountProcessing", count18, "");

        int count19 = 0;
        sendMqtt(DEFAULT_DEVICE_ID, "巡检-问题数", "PatrolInspectionOrderQuestionCount", count19, "");


        int count20 = NumberUtil.round(NumberUtil.mul(NumberUtil.div(count11 + count15 + count16 - count18, count8 + count12 + count16), 100), 0).intValue();
        sendMqtt(DEFAULT_DEVICE_ID, "工单-总完成率", "WorkOrderCR", count20, "%");

        int count21 = NumberUtil.round(NumberUtil.mul(NumberUtil.div(count11, count8), 100), 0).intValue();
        sendMqtt(DEFAULT_DEVICE_ID, "维修-总完成率", "RepairOrderCR", count21, "%");

        int count22 = NumberUtil.round(NumberUtil.mul(NumberUtil.div(count15, count12), 100), 0).intValue();
        sendMqtt(DEFAULT_DEVICE_ID, "维保-总完成率", "MaintenanceOrderCR", count22, "%");

        int count23 = NumberUtil.round(NumberUtil.mul(NumberUtil.div(count16 - count18, count16), 100), 0).intValue();
        sendMqtt(DEFAULT_DEVICE_ID, "点巡检-总完成率", "PatrolInspectionOrderCR", count23, "%");


        int count24 = count9 + count13 + count17;
        sendMqtt(DEFAULT_DEVICE_ID, "工单-今日总数", "WorkOrderCountToDay", count24, "");

        rwoExample.clear();
        RepairWorkOrderExample.Criteria rwoCriteria4 = rwoExample.createCriteria();
        rwoCriteria4.andRepStateEqualTo(11);
        rwoCriteria4.andCreateTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        int repairTodayFinished = (int) repairWorkOrderMapper.countByExample(rwoExample);
        uwoExample.clear();
        UpkeepWorkOrderExample.Criteria uwoCriteria4 = uwoExample.createCriteria();
        uwoCriteria4.andUpkeepStateEqualTo(11);
        uwoCriteria4.andCreateTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        int upkeepTodayFinished = (int) upkeepWorkOrderMapper.countByExample(uwoExample);
        pwoExample.clear();
        PatrolWorkOrderExample.Criteria pwoCriteria4 = pwoExample.createCriteria();
        pwoCriteria4.andStateEqualTo(5);
        pwoCriteria4.andCreateTimeGreaterThanOrEqualTo(DateUtil.beginOfDay(date));
        int patrolTodayFinished = (int) patrolWorkOrderMapper.countByExample(pwoExample);
        int count25 = repairTodayFinished + upkeepTodayFinished + patrolTodayFinished;
        sendMqtt(DEFAULT_DEVICE_ID, "工单-今日已完成数", "WorkOrderCountToDayFinished", count25, "");

        int count26 = count24 - count25;
        sendMqtt(DEFAULT_DEVICE_ID, "工单-今日未完成数", "WorkOrderCountToDayUnfinished", count26, "");


    }


}

























